class Tools {
    // 获取dom元素
    _c = tagName => document.createElement(tagName)
    $ = id => document.getElementById(id)
}

class snakeGame extends Tools {
    constructor(foodContext) {
            super()
                //定义蛇的身子
            this.body = [
                    { x: 2, y: 0 },
                    { x: 1, y: 0 },
                    { x: 0, y: 0 }
                ]
                // 定义一节蛇的身子的宽度和高度
            this.width = 15;
            this.height = 15;
            //获取游戏地图
            this.map = this.$('map')
                // 蛇的方向，默认往右边跑
            this.direction = 'right'
            this.keyboardEvent()
            if (foodContext instanceof Food) {
                this.f = foodContext
            } else {
                alert('需要传入food实例')
            }
        }
        // 键盘事件，控制蛇的方向
    keyboardEvent() {
        document.onkeydown = (e) => {
            switch (e.code) {
                // 左
                case "ArrowLeft":
                    this.direction = 'left'
                    break;
                    // 上
                case "ArrowUp":
                    this.direction = 'up'
                    break;
                    // 右
                case "ArrowRight":
                    this.direction = 'right'
                    break
                    // 下
                case "ArrowDown":
                    this.direction = 'down'
            }
        }
    }

    // 画蛇
    display() {

            // this.map.innerHTML = ''误差别攻击
            this.body.forEach(item => {
                if (item.oldNode) {
                    this.map.removeChild(item.oldNode)
                }
                let div = this._c('div')
                    //蛇身添加颜色
                div.style.background = 'black'
                div.style.border = '1px solid white'
                div.style.boxSizing = 'border-box'
                div.style.width = this.width + 'px'
                div.style.height = this.height + 'px'
                    // 排成一排
                div.style.position = 'absolute'
                    // left=x*自身宽度
                    // top=y*自身高度
                div.style.left = this.width * item.x + 'px'
                div.style.top = this.height * item.y + 'px'
                    // 将div添加到旧节点
                item.oldNode = div
                this.map.appendChild(div)
                    // 根据蛇身的数据创建蛇
            })
        }
        // 蛇运动
    run() {
            // 蛇在水平方向运动起来
            // 获取蛇尾数组数据
            let final = this.body.pop()
                // 蛇头x轴+1
                // 获取蛇头，利用蛇头数据，计算下一节身子
                // 对蛇头进行浅拷贝
            let first = {...this.body[0] }
                // 取出蛇头x、y轴
                // 构析赋值
            let { x } = first
            let { y } = first
            switch (this.direction) {
                case 'up':
                    y -= 1;
                    break
                case 'down':
                    y += 1;
                    break
                case 'left':
                    x -= 1;
                    break
                case 'right':
                    x += 1;
            }
            // 赋值给蛇尾
            final.x = x
            final.y = y
            let snakeHeadX = x * this.width
            let snakeHeadY = y * this.height
            if (snakeHeadX == this.f.foodX && snakeHeadY == this.f.foodY) {
                this.body.push({ x, y })
                this.f.removeFood()
                this.f.creatFood()

            }
            // 在前面添加
            this.body.unshift(final)
                // 重新绘制蛇
            this.display()
                // 判定死亡
            if (this.isDea(snakeHeadX, snakeHeadY)) {
                b.pauseGame()
                alert('gameOver')
                return
            }
            console.log(this.body.item);

            // console.log('x轴' + this.body.x * this.width);
            // console.log('y轴' + this.body.y * this.height);
        }
        // 判断死亡
    isDea = (x, y) => {
        if (x < 0 || x > this.map.offsetWidth - this.width || (y < 0 && this.direction == 'up') || y > this.map.offsetHeight - this.height) {
            return true
        }
    }
}
// 按键绑定类
class btnController extends Tools {
    constructor(snakeContext, foodContext) {
            super()
            this.startBtn = this.$('start')
            this.pauseBtn = this.$('pause')
            this.stopBtn = this.$('stop')
            this.map = this.$('map')
                // 判断传入的实例是不是snakeGame
            if (snakeContext instanceof snakeGame && foodContext instanceof Food) {
                this.s = snakeContext
                this.f = foodContext
                this.btnEvent()
            } else {

                alert('传入实例有错')
            }
        }
        // 绑定按钮事件
    btnEvent = () => {
        this.startBtn.onclick = this.startGame
        this.pauseBtn.onclick = this.pauseGame
        this.stopBtn.onclick = this.stopGame
    }
    startGame = () => {
        // if (this.interval) {
        //     clearInterval(this.interval)
        // }
        this.f.creatFood()
        this.interval = setInterval(() => {
            this.s.run()
        }, 100)
    }
    pauseGame = () => {
        clearInterval(this.interval)
    }
    stopGame = () => {
        this.f.removeFood()
        this.map.innerHTML = ''
        this.s.body = [
            { x: 2, y: 0 },
            { x: 1, y: 0 },
            { x: 0, y: 0 }
        ]
        this.s.display()
        clearInterval(this.interval)
        this.s.direction = 'right'
    }
}
// Food类
class Food extends Tools {
    constructor() {
            super()
                // 定义食物宽度
            this.width = 15;
            this.height = 15;
            this.map = this.$('map')

        }
        // 食物定位
    positionFood = () => {
            let left = Math.floor(Math.random() * (this.map.offsetWidth - this.width))
            let top = Math.floor(Math.random() * (this.map.offsetHeight - this.height))
            if (left % this.width == 0 && top % this.height == 0) {
                this.foodX = left
                this.foodY = top
            } else {
                this.positionFood()
            }
        }
        // 创建食物
    creatFood = () => {
        // 如果有food就不再创建
        if (this.food) {
            return
        }
        console.log(123);
        let food = this._c('div')
        food.style.width = this.width + 'px'
        food.style.height = this.height + 'px'
        food.style.background = 'yellow'
        food.style.border = '1px solid black'
        this.positionFood()
        food.style.position = 'absolute'
        food.style.left = this.foodX + 'px'
        food.style.top = this.foodY + 'px'
        this.food = food
        this.map.appendChild(food)
    }
    removeFood = () => {
        this.map.removeChild(this.food)
        this.food = null
    }
}
let f = new Food()
let s = new snakeGame(f)
s.display()
    // setInterval(() => {
    //     s.run()
    // }, 100)
let b = new btnController(s, f)